﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Furion.DatabaseAccessor;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using YBlog.Application.Contracts;
using YBlog.Application.Contracts.System.DataItems;
using YBlog.Core.System;

namespace YBlog.Application.System
{
    /// <summary>
    /// 数据项
    /// </summary>
    [ApiDescriptionSettings("System")]
    public class DataItemService: IBaseService
    {
        #region 缓存Key
        private readonly string _dataItemCategoryAll = "DataItemCategoryAll";
        private readonly string _dataItemAll = "DataItemAll";
        private readonly string _dataItemDetailAll = "DataItemDetailAll";
        #endregion
        private readonly IRepository<DataItem> _dataItemRepository;
        private readonly IRepository<DataItemDetail> _dataItemDetailRepository;
        private readonly IMemoryCacheService _memoryCacheService;
        private readonly IRepository<DataItemCategory> _dataItemCategoryRepository;

        public DataItemService(IRepository<DataItem> dataItemRepository, IRepository<DataItemCategory> dataItemCategoryRepository, IRepository<DataItemDetail> dataItemDetailRepository, IMemoryCacheService memoryCacheService)
        {
            _dataItemRepository = dataItemRepository;
            _dataItemCategoryRepository = dataItemCategoryRepository;
            _dataItemDetailRepository = dataItemDetailRepository;
            _memoryCacheService = memoryCacheService;

        }

        #region 查询
        /// <summary>
        /// 获取数据项
        /// </summary>
        /// <param name="id">数据项Id</param>
        /// <returns></returns>
        public async Task<DataItemDto> GetDataItem(string id)
        {
            return await Task.FromResult(GetDataItemAll().Result.Find(d => d.Id == id));
        }

        /// <summary>
        /// 根据数据项Id获取数据项明细Id
        /// </summary>
        /// <param name="dataItemId">数据项Id</param>
        /// <returns></returns>
        public async Task<List<DataItemDetailDto>> GetDetails(string dataItemId)
        {
            return await Task.FromResult(GetDetailAll().Result.FindAll(d => d.DataItemId == dataItemId));
        }

        /// <summary>
        /// 根据分类Id获取数据项列表
        /// </summary>
        /// <param name="categoryId">分类Id</param>
        /// <returns></returns>
        public async Task<List<DataItemDto>> GetListByCategoryId(string categoryId)
        {
            return await Task.FromResult(GetDataItemAll().Result.FindAll(d => d.DataItemCategoryId == categoryId));
        }

        /// <summary>
        /// 获取全部数据项
        /// </summary>
        /// <returns></returns>
        [InitializationCache]
        public async Task<List<DataItemDto>> GetDataItemAll()
        {
            return await _memoryCacheService.GetOrCreateAsync(_dataItemAll, async entry =>
            {
                return await Task.FromResult(_dataItemRepository.AsEnumerable(false).Adapt<List<DataItemDto>>());
            });
        }

        /// <summary>
        /// 获取全部数据项明细
        /// </summary>
        /// <returns></returns>
        [InitializationCache]
        public async Task<List<DataItemDetailDto>> GetDetailAll()
        {
            return await _memoryCacheService.GetOrCreateAsync(_dataItemDetailAll, async entry =>
            {
                return await Task.FromResult(
                    _dataItemDetailRepository.AsEnumerable(false).Adapt<List<DataItemDetailDto>>()
                    );
            });
        }

        /// <summary>
        /// 获取全部数据项分类
        /// </summary>
        /// <returns></returns>
        [InitializationCache]
        public async Task<List<DataItemCategoryDto>> GetDataItemCategoryAll()
        {
            return await _memoryCacheService.GetOrCreateAsync(_dataItemCategoryAll, async entry =>
            {
                var allCategorys = (await _dataItemCategoryRepository.AsAsyncEnumerable(false)).Adapt<List<DataItemCategoryDto>>();

                var resultCategorys = new List<DataItemCategoryDto>();
                foreach (var category in allCategorys)
                {
                    var parent = allCategorys.Find(c => c.Id == category.ParentId);
                    if (parent == null)
                        resultCategorys.Add(category);
                    else
                    {
                        parent.Children ??= new List<DataItemCategoryDto>();
                        parent.Children.Add(category);
                    }
                }
                return await Task.FromResult(resultCategorys);
            });
        }
        #endregion

        #region 提交数据
        /// <summary>
        /// 数据项插入
        /// </summary>
        /// <param name="dataItemDto">数据项</param>
        /// <returns></returns>
        [UnitOfWork]
        public async Task InsertAsync(DataItemCreateUpdateDto dataItemDto)
        {
            var dataItem = (await _dataItemRepository.InsertNowAsync(dataItemDto.Adapt<DataItem>())).Entity;
            foreach(var detail in dataItemDto.Details)
            {
                detail.DataItemId = dataItem.Id;
            } 
            await _dataItemDetailRepository.InsertNowAsync(dataItemDto.Details.Adapt<List<DataItemDetail>>());
            await _memoryCacheService.RemoveAsync(_dataItemDetailAll);
        }
        /// <summary>
        /// 数据项修改
        /// </summary>
        /// <param name="dataItemDto">数据项</param>
        /// <returns></returns>
        [UnitOfWork]
        public async Task UpdateAsync(DataItemCreateUpdateDto dataItemDto)
        {
            await _dataItemRepository.UpdateNowAsync(dataItemDto.Adapt<DataItem>());
            var dbDetails = (await GetDetailAll()).FindAll(o => o.DataItemId == dataItemDto.Id);
            foreach(var detail in dataItemDto.Details.Adapt<List<DataItemDetail>>())
            {
                var dbDetail = dbDetails.Find(o => o.Id == detail.Id);
                if(dbDetail != null)
                {
                    await _dataItemDetailRepository.UpdateAsync(detail);
                    dbDetails.Remove(dbDetail);
                }
                else
                {
                    detail.DataItemId = dataItemDto.Id;
                    await _dataItemDetailRepository.InsertAsync(detail);
                }
            }
            if(dbDetails.Count > 0)
                await _dataItemDetailRepository.FakeDeleteAsync(dbDetails); // 假删除
            if(await _dataItemDetailRepository.SaveNowAsync() > 0)
            {
                await _memoryCacheService.RemoveAsync(_dataItemDetailAll);
            }
        }
        #endregion
    }
}
